/**
 *
 * © Bahadir Zeren 2011
 * bzeren@gmail.com
 * No warranties, express or implied, are made for this program.
 *
 */

package org.baatar.net.tcp;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import org.apache.log4j.Logger;
import org.baatar.net.message.IRequest;
import org.baatar.net.message.IResponse;

/**
 * Thread class which is generated to process each incoming Request messages.
 * 
 * @author b_zeren
 */
public class TCPMessageProcessThread extends Thread {

    private IMessageProcessor messageProcessor = null;
    private Socket clientSocket = null;
    private Logger logger = null;

    /**
     * Constructor of the TCPMessageProcessThread.
     * 
     * @param messageProcessor specific processor for the Request message.
     * 
     * @param clientSocket the socket which sends the Request message to be 
     * processed.
     * 
     * @param logger Logger object of the TCP service to log processing steps
     * or exceptions.
     * 
     */
   public TCPMessageProcessThread(IMessageProcessor messageProcessor,
                                    Socket clientSocket,
                                    Logger logger) {
        this.messageProcessor = messageProcessor;
        this.clientSocket = clientSocket;
        this.logger = logger;
    }

    /**
     * Main run() method of the TCPMessageProcessThread object.
     * 
    * @see Thread
     */
    @Override
    public void run() {
        try {
            String clientIP = clientSocket.getInetAddress().getHostAddress();
            int clientPortNr = clientSocket.getPort();

            InputStream inputStream = clientSocket.getInputStream();
            OutputStream outputStream = clientSocket.getOutputStream();
            try {
                ObjectInputStream objInputStream = null;
                ObjectOutputStream objOutputStream = null;
                try {
                    IRequest request = null;

                    objInputStream = new ObjectInputStream(inputStream);
                    objOutputStream = new ObjectOutputStream(outputStream);
                    request = (IRequest) objInputStream.readObject();

                    IResponse response = null;

                    try {
                        response = messageProcessor.processMessage(clientIP,
                                                                    clientPortNr,
                                                                    request,
                                                                    logger);
                        objOutputStream.writeObject(response);
                    } catch (Exception ex) {
                        objOutputStream.writeObject(ex);
                    }

                    objOutputStream.flush();
                    objOutputStream.reset();

                } finally {
                    if (objInputStream != null)
                        objInputStream.close();
                    if (objOutputStream != null)
                        objOutputStream.close();
                }
            } finally {
                inputStream.close();
                outputStream.close();
                clientSocket.close();
            }
        } catch (Exception ex) {
            logger.error(ex.getMessage());
        }
    }
}
